/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import javax.microedition.lcdui.*;
import java.io.IOException;
import java.util.Random;
import java.util.Vector;
/**
 *
 * @author Andik Taufiq
 * 2010, September 19
 */
public class MainCanvas extends Canvas implements Runnable {
    private Display display;
    private Mockup8Puzzle midlet;
    private int headerHeight = 30;
    private int footerHeight = 20;

    public static Font plainFont;
    public static Font boldFont;
    public static Font mediumPlainFont;
    public static Font mediumBoldFont;

    private Image header;
    private Image footer;
    private Image background;

    private int pageId = 1;
    /*
     * ID's of each page :
     *      1   : Main Menu
     *      2   : Simulation Page
     *      3   : Settings
     *      4   : Instruction
     *      5   : About
     *      6   : Transition Page
     */

    private int index = 1;

    // Main Menu ---------------------------------------------------------------
    private Menu menu;
    private Vector menus;
    private static int nbMenu = 5;
    private String[] menuLabel;
    private String[] menuDescription;

    // Transition Page ---------------------------------------------------------
    private int prevPage;
    private int nextPage;
    private int xPage = 0;
    private int transitionPhase = 0;
    private int transitionBarWidth = 0;

    // Simulation Page ---------------------------------------------------------
    private Board board;
    private int[] initialState;
    private int[] state;
    private int[] finalState;
    private static int NB_ELEMENT = 9;
    private Settings settings;
    private int xBoard;
    private boolean solving = false;
    private String solver = "Solver: ";
    private String current = "Current: ";
    private String goal = "Goal: ";
    private int step = 0;
    private int trackIndex = 1;
    private boolean resultState = false;

    // Settings Page -----------------------------------------------------------
    private int xSettings;

    // About Page --------------------------------------------------------------
    private String myCredit;
    private String myId;
    private String myContact;
    private String myCopyright;
    private int xAbout;

	// Instruction
	private String instruction;
	private int xInstruction;
	private int yInstruction;
	private Image inst;
	private Graphics graphInst;
	private CustomScrollBar csb;
	private int instructionHeight;
	private int windowHeight = 245;

	// Dialog
	private AlertDialog ad;

    public MainCanvas(Mockup8Puzzle midlet, Display display) {
        setFullScreenMode(true);	// set agar canvas ditampilkan secara fullscreen
        this.midlet = midlet;
        this.display = display;
        try {
            header = Image.createImage("/header.png");
            footer = Image.createImage("/footer.png");
            background = Image.createImage(240, 320);
			inst = Image.createImage(240, 320);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        background = midlet.splash;

        plainFont 	= Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        boldFont	= Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL);
        mediumPlainFont	= Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
        mediumBoldFont	= Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_MEDIUM);

        // Main Menu -----------------------------------------------------------
        menuLabel = new String[nbMenu];
        menuLabel[0] = "New Simulation";
        menuLabel[1] = "Settings";
        menuLabel[2] = "Instruction";
        menuLabel[3] = "About";
        menuLabel[4] = "Exit";
        menuDescription = new String[nbMenu];
        menuDescription[0] = "Go to simulation page";
        menuDescription[1] = "Set the parameters";
        menuDescription[2] = "How to simulate";
        menuDescription[3] = "About 8-puzzle simulator";
        menuDescription[4] = "Quit from application";
        menus = new Vector();
        for (int i = 0; i < nbMenu; i++) {
            menu = new Menu(5, 45 + (i * 47), i+1, index, i+1, menuLabel[i], menuDescription[i]);
            menus.addElement(menu);
        }

        // Simulation Page -----------------------------------------------------
        settings = new Settings();
        initialState = new int[NB_ELEMENT];
        state = new int[NB_ELEMENT];
        for (int i = 0; i < NB_ELEMENT; i++) {
            state[i] = settings.finalState[i];
        }
        finalState = new int[NB_ELEMENT];
        board = new Board(state, getWidth()/2, getHeight()/2 - 40);
        xBoard = (getWidth() * 3) / 2;

        // Settings Page -------------------------------------------------------
        xSettings = getWidth();

        // About Page ----------------------------------------------------------
        myCredit = "Developed by";
        myId = "Andik Taufiq";
        myContact = "Contact: andik.taufiq@gmail.com";
        myCopyright = "copyright 2010";
        xAbout = getWidth()/2;

		// Instruction
		instruction = "Simply play the puzzle with arrow keys (LEFT, RIGHT, UP, and DOWN) until the sequence number of each tiles appears into their right position, which is called as final state. This state can be choosen from Settings feature (Main Menu -> Settings -> Final State -> choose which state that you want). Only three combinations of final state available on this application: [0 1 2 3 4 5 6 7 8], [1 2 3 4 5 6 7 8 0], and [1 2 3 8 0 4 7 6 5]. You can also create a random formation of tiles with random function, so you can solve it by yourself. If you want to use an AI solver agent for this puzzle problem, you can choose the type of algorythms from Settings feature, so the computer can helps you to solve the problem. By the purpose, this application's just a simulator for solving every cases related to eight puzzle problem, so you can also do that simulation and get your experiences with the ways of computer's thinking. Just enjoy it and share with your friends!!";
		xInstruction = getWidth();
		yInstruction = 50;
		graphInst = inst.getGraphics();
		csb = new CustomScrollBar(getWidth() - 7, yInstruction, windowHeight, 5);

		// Dialog
		ad = new AlertDialog("Exit", "Are you sure want to exit from this application?", AlertDialog.ALERTDIALOG_QUESTION);
	}

    public void randomize(int step, int[] state) {
        int tempRand = 0;
        int tempRand2 = 0;
        Random rand = new java.util.Random();
        for (int i = 0; i < step; i++) {
            tempRand2 = rand.nextInt();
            tempRand = Math.abs(tempRand2 % 4);
            switch (tempRand) {
                case 0:
                    moveUp(state);
                break;
                case 1:
                    moveDown(state);
                break;
                case 2:
                    moveRight(state);
                break;
                case 3:
                    moveLeft(state);
                break;
                default:
                break;
            }
        }
    }

    public void moveLeft(int[] state) {
        int tempInt = 0;
        for (int i = 0; i < state.length; i++) {
            if (state[i] == 0) {
                tempInt = i;
            }
        }
        if ((tempInt%3) > 0) {
            int temp = state[tempInt-1];
            state[tempInt-1] = 0;
            state[tempInt] = temp;
        }
    }

    public void moveRight(int[] state) {
        int tempInt = 0;
        for (int i = 0; i < state.length; i++) {
            if (state[i] == 0) {
                tempInt = i;
            }
        }
        if ((tempInt%3) < 2) {
            int temp = state[tempInt+1];
            state[tempInt+1] = 0;
            state[tempInt] = temp;
        }
    }

    public void moveUp(int[] state) {
        int tempInt = 0;
        for (int i = 0; i < state.length; i++) {
            if (state[i] == 0) {
                tempInt = i;
            }
        }
        if (tempInt > 2) {
            int temp = state[tempInt-3];
            state[tempInt-3] = 0;
            state[tempInt] = temp;
        }
    }

    public void moveDown(int[] state) {
        int tempInt = 0;
        for (int i = 0; i < state.length; i++) {
            if (state[i] == 0) {
                tempInt = i;
            }
        }
        if (tempInt < 6) {
            int temp = state[tempInt+3];
            state[tempInt+3] = 0;
            state[tempInt] = temp;
        }
    }

    private void drawSoftMenu(Graphics g, String leftMenu, String centerMenu, String rightMenu) {
        g.setColor(0x8EBCE8);
        g.setFont(plainFont);
        if (leftMenu != null) {
            g.drawString(leftMenu, 4, getHeight() - 2,Graphics.BOTTOM|Graphics.LEFT);
        }
        if (rightMenu != null) {
            g.drawString(rightMenu, getWidth() - 4, getHeight() - 2,Graphics.BOTTOM|Graphics.RIGHT);
        }
        g.setFont(boldFont);
        if (centerMenu != null) {
            g.drawString(centerMenu, getWidth() / 2, getHeight() - 2,Graphics.BOTTOM|Graphics.HCENTER);
        }
    }

	private void drawInstruction(String instruction, int xInstruction, int yInstruction) {
		graphInst.drawImage(background, 0, 0, Graphics.TOP | Graphics.LEFT);
		drawWrapText(graphInst, splitString(instruction), plainFont, 0xFFFFFF, 1, 10, yInstruction, 220);
		instructionHeight = calculateArea(graphInst, splitString(instruction), plainFont, 0xFFFFFF, 1, 10, yInstruction + 50, 220);
		csb.setBarProperties(50, yInstruction, instructionHeight, windowHeight);
		csb.paint(graphInst);
		//g.drawImage(inst, xInstruction, 0, Graphics.TOP | Graphics.LEFT);
		//drawWrapText(g, splitString(instruction), plainFont, 0xFFFFFF, 1, xInstruction + 10, yInstruction + 50, 220);
	}

    protected void paint(Graphics g) {
        // background
        g.drawImage(background, 0, 0, Graphics.TOP | Graphics.LEFT);
        //System.out.println("index = " + index);
        switch (pageId) {
            //------------------------------------------------------------------
            case 1: // Main Menu
                

                // content
                for (int i = 0; i < menus.size(); i++) {
                    ((Menu) menus.elementAt(i)).index = this.index;
                    ((Menu) menus.elementAt(i)).x = 5;
                    ((Menu) menus.elementAt(i)).paint(g);
                }
                //drawCurrentPageContent(g, currentPage);
                display.callSerially(this);
				if (ad.showed == true) {
					ad.paint(g);
				}
				// header / title bar
                g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                g.setColor(0x537698);
                g.setFont(mediumBoldFont);
                g.drawString("8-Puzzle Simulator",getWidth()/2+1,6,Graphics.TOP|Graphics.HCENTER);
                g.setColor(0x8EBCE8);
                g.drawString("8-Puzzle Simulator",getWidth()/2,5,Graphics.TOP|Graphics.HCENTER);
                // footer / option bar / menu bar
                g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
				if (ad.showed == true) {
					drawSoftMenu(g, "Yes", null, "No");
				} else {
					drawSoftMenu(g, null, "Select", "Exit");
				}
            break;
            //------------------------------------------------------------------
            case 2: // Simulation Page
               // header / title bar
                g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                g.setColor(0x537698);
                g.setFont(mediumBoldFont);
                g.drawString("Simulation",51,6,Graphics.TOP|Graphics.LEFT);
                g.setColor(0x8EBCE8);
                g.drawString("Simulation",50,5,Graphics.TOP|Graphics.LEFT);
                g.drawImage(menu.icon1, 10, 8, Graphics.TOP | Graphics.LEFT);

				board.state = state;
				board.paint(g);
				g.setFont(plainFont);
				g.drawString(solver + settings.solver,10,225,Graphics.TOP|Graphics.LEFT);
				g.drawString(current + strArray(state),10,242,Graphics.TOP|Graphics.LEFT);
				g.drawString(goal + strArray(settings.finalState),10,259,Graphics.TOP|Graphics.LEFT);
				display.callSerially(this);
				// footer / option bar / menu bar
				g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
				if (!solving) {
					drawSoftMenu(g, "Randomize", "Solve", "Main Menu");
				} else if (solving) {
					if (resultState)
						drawSoftMenu(g, "Randomize", "Solve", "Main Menu");
					else
						drawSoftMenu(g, "", "", "");
				}
            break;
            //------------------------------------------------------------------
            case 3: // Settings
                // header / title bar
                g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                g.setColor(0x537698);
                g.setFont(mediumBoldFont);
                g.drawString("Settings",51,6,Graphics.TOP|Graphics.LEFT);
                g.setColor(0x8EBCE8);
                g.drawString("Settings",50,5,Graphics.TOP|Graphics.LEFT);
                g.drawImage(menu.icon2, 10, 8, Graphics.TOP | Graphics.LEFT);

                settings.paintMenu(g);

                // footer / option bar / menu bar
                g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                drawSoftMenu(g, "", "", "Done");
            break;
            //------------------------------------------------------------------
            case 4: // Instruction
				g.drawImage(inst, xInstruction, 0, Graphics.TOP | Graphics.LEFT);
				
				// header / title bar
                g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                g.setColor(0x537698);
                g.setFont(mediumBoldFont);
                g.drawString("Instruction",51,6,Graphics.TOP|Graphics.LEFT);
                g.setColor(0x8EBCE8);
                g.drawString("Instruction",50,5,Graphics.TOP|Graphics.LEFT);
                g.drawImage(menu.icon3, 10, 8, Graphics.TOP | Graphics.LEFT);

				// footer / option bar / menu bar
                g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                drawSoftMenu(g, "", "Ok", "");
            break;
            //------------------------------------------------------------------
            case 5: // About
                // header / title bar
                g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                g.setColor(0x537698);
                g.setFont(mediumBoldFont);
                g.drawString("About",51,6,Graphics.TOP|Graphics.LEFT);
                g.setColor(0x8EBCE8);
                g.drawString("About",50,5,Graphics.TOP|Graphics.LEFT);
                g.drawImage(menu.icon4, 10, 8, Graphics.TOP | Graphics.LEFT);

                g.setColor(0x8EBCE8);
                g.setFont(plainFont);
                g.drawString(myCredit, xAbout, 70, Graphics.TOP | Graphics.HCENTER);
                g.setFont(boldFont);
                g.drawString(myId, xAbout, 90, Graphics.TOP | Graphics.HCENTER);
                g.setColor(0x4A77A2);
                g.setFont(plainFont);
                g.drawString(myContact, xAbout, 110, Graphics.TOP | Graphics.HCENTER);
                g.drawString(myCopyright, xAbout, 130, Graphics.TOP | Graphics.HCENTER);

                // footer / option bar / menu bar
                g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                drawSoftMenu(g, "", "Ok", "");
            break;
            //------------------------------------------------------------------
            case 6: // Transition Page
                switch (prevPage) {
                    case 1:
                        
                        if (nextPage == 2) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                            } else if (transitionPhase == 2) {
                                g.setColor(0x8EBCE8);
                                g.setFont(boldFont);
                                g.drawString("Loading...",getWidth()/2,180,Graphics.TOP|Graphics.HCENTER);
                                g.setColor(0x3F73A4);
                                g.drawRect(20,200,200,4);
                                g.setColor(0xB3D2EF);
                                g.fillRect(22,202,transitionBarWidth,1);
                            } else if (transitionPhase == 3) {
                                board.x = xBoard;
                                board.xTilesRef = xBoard - (board.boardImg.getWidth() / 2) + 9;
                                board.paint(g);
                                g.setFont(plainFont);
                                g.drawString(solver + settings.solver,xBoard + 10,230,Graphics.TOP|Graphics.LEFT);
                                g.drawString(current + strArray(state),xBoard + 10,245,Graphics.TOP|Graphics.LEFT);
                                g.drawString(goal + strArray(settings.finalState),xBoard + 10,260,Graphics.TOP|Graphics.LEFT);
                            }
                        } else if (nextPage == 3) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                                settings.xRef = xSettings + 10;
                                settings.paintMenu(g);
                            }
                        } else if (nextPage == 4) {
							if (transitionPhase == 1) {
								for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
								g.drawImage(inst, xInstruction, 0, Graphics.TOP | Graphics.LEFT);
							}
                        } else if (nextPage == 5) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                                g.setColor(0x8EBCE8);
                                g.setFont(plainFont);
                                g.drawString(myCredit, xAbout, 70, Graphics.TOP | Graphics.HCENTER);
                                g.setFont(boldFont);
                                g.drawString(myId, xAbout, 90, Graphics.TOP | Graphics.HCENTER);
                                g.setColor(0x4A77A2);
                                g.setFont(plainFont);
                                g.drawString(myContact, xAbout, 110, Graphics.TOP | Graphics.HCENTER);
                                g.drawString(myCopyright, xAbout, 130, Graphics.TOP | Graphics.HCENTER);
                            }
                        }
                        display.callSerially(this);
						// header / title bar
                        g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                        g.setColor(0x537698);
                        g.setFont(mediumBoldFont);
                        g.drawString("8-Puzzle Simulator",getWidth()/2+1,6,Graphics.TOP|Graphics.HCENTER);
                        g.setColor(0x8EBCE8);
                        g.drawString("8-Puzzle Simulator",getWidth()/2,5,Graphics.TOP|Graphics.HCENTER);
                        // footer / option bar / menu bar
                        g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                        //drawSoftMenu(g, null, "Select", "Exit");
                    break;
                    case 2:
                        // header / title bar
                        g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                        g.setColor(0x537698);
                        g.setFont(mediumBoldFont);
                        g.drawString("Simulation",51,6,Graphics.TOP|Graphics.LEFT);
                        g.setColor(0x8EBCE8);
                        g.drawString("Simulation",50,5,Graphics.TOP|Graphics.LEFT);
                        g.drawImage(menu.icon1, 10, 8, Graphics.TOP | Graphics.LEFT);
                        if (nextPage == 1) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                                board.x = xBoard;
                                board.xTilesRef = xBoard - (board.boardImg.getWidth() / 2) + 9;
                                board.paint(g);
                                g.setFont(plainFont);
                                g.drawString(solver + settings.solver,xBoard + 10,230,Graphics.TOP|Graphics.LEFT);
                                g.drawString(current + strArray(state),xBoard + 10,245,Graphics.TOP|Graphics.LEFT);
                                g.drawString(goal + strArray(settings.finalState),xBoard + 10,260,Graphics.TOP|Graphics.LEFT);
                            }
                        }
                        display.callSerially(this);
                        // footer / option bar / menu bar
                        g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                    break;
                    case 3:
                        // header / title bar
                        g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                        g.setColor(0x537698);
                        g.setFont(mediumBoldFont);
                        g.drawString("Settings",51,6,Graphics.TOP|Graphics.LEFT);
                        g.setColor(0x8EBCE8);
                        g.drawString("Settings",50,5,Graphics.TOP|Graphics.LEFT);
                        g.drawImage(menu.icon2, 10, 8, Graphics.TOP | Graphics.LEFT);

                        if (nextPage == 1) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                                settings.xRef = xSettings + 10;
                                settings.paintMenu(g);
                            }
                        }
                        display.callSerially(this);
                        // footer / option bar / menu bar
                        g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                    break;
                    case 4:
						// header / title bar
						g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
						g.setColor(0x537698);
						g.setFont(mediumBoldFont);
						g.drawString("Instruction",51,6,Graphics.TOP|Graphics.LEFT);
						g.setColor(0x8EBCE8);
						g.drawString("Instruction",50,5,Graphics.TOP|Graphics.LEFT);
						g.drawImage(menu.icon3, 10, 8, Graphics.TOP | Graphics.LEFT);
						if (nextPage == 1) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
								xInstruction += 10;
                                g.drawImage(inst, xInstruction, 0, Graphics.TOP | Graphics.LEFT);
                            }
                        }
                        display.callSerially(this);
						// footer / option bar / menu bar
						g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                    break;
                    case 5:
                        // header / title bar
                        g.drawImage(header, 0, 0, Graphics.TOP | Graphics.LEFT);
                        g.setColor(0x537698);
                        g.setFont(mediumBoldFont);
                        g.drawString("About",51,6,Graphics.TOP|Graphics.LEFT);
                        g.setColor(0x8EBCE8);
                        g.drawString("About",50,5,Graphics.TOP|Graphics.LEFT);
                        g.drawImage(menu.icon4, 10, 8, Graphics.TOP | Graphics.LEFT);
                        if (nextPage == 1) {
                            if (transitionPhase == 1) {
                                for (int i = 0; i < menus.size(); i++) {
                                    ((Menu) menus.elementAt(i)).index = this.index;
                                    ((Menu) menus.elementAt(i)).x = this.xPage + 5;
                                    ((Menu) menus.elementAt(i)).paint(g);
                                }
                                g.setColor(0x8EBCE8);
                                g.setFont(plainFont);
                                g.drawString(myCredit, xAbout, 70, Graphics.TOP | Graphics.HCENTER);
                                g.setFont(boldFont);
                                g.drawString(myId, xAbout, 90, Graphics.TOP | Graphics.HCENTER);
                                g.setColor(0x4A77A2);
                                g.setFont(plainFont);
                                g.drawString(myContact, xAbout, 110, Graphics.TOP | Graphics.HCENTER);
                                g.drawString(myCopyright, xAbout, 130, Graphics.TOP | Graphics.HCENTER);
                            }
                        }
                        
                        display.callSerially(this);
                        // footer / option bar / menu bar
                        g.drawImage(footer, 0, getHeight(), Graphics.BOTTOM | Graphics.LEFT);
                    break;
                }
            break;
        }
		
    }

    protected void keyPressed(int keyCode) {
		if (ad.showed == true) {
			ad.keyPressed(keyCode);
			if (keyCode == -6) {
				midlet.exitMIDlet();
			}
		} else {
			int gameCode = getGameAction(keyCode);
			//System.out.println("keyCode = " + keyCode);
			//System.out.println("gameCode = " + gameCode);
			switch (pageId) {
				//------------------------------------------------------------------
				case 1: // Main Menu
					switch (gameCode) {
						case UP:
							if (index > 1) {
								index--;
							} else {
								index = nbMenu;
							}
						break;
						case DOWN:
							if (index < nbMenu) {
								index++;
							} else {
								index = 1;
							}
						break;
						case FIRE:
							if (index == 1) {
								for (int i = 0; i < NB_ELEMENT; i++) {
									state[i] = settings.finalState[i];
									board.state[i] = state[i];
								}
								transitionBarWidth = 0;
								xPage = 0;
								prevPage = 1;
								nextPage = 2;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 2) {
								xPage = 0;
								xSettings = getWidth();
								prevPage = 1;
								nextPage = 3;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 3) {
								xPage = 0;
								xInstruction = getWidth();
								prevPage = 1;
								nextPage = 4;
								transitionPhase = 1;
								pageId = 6;
								drawInstruction(instruction, xInstruction, yInstruction);
							} else if (index == 4) {
								xPage = 0;
								xAbout = (getWidth()*3)/2;
								prevPage = 1;
								nextPage = 5;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 5) {
								if (ad.showed == true) {
									midlet.exitMIDlet();
								} else {
									ad.showed = true;
								}
							}
						break;
						case RIGHT:
							if (index == 1) {
								for (int i = 0; i < NB_ELEMENT; i++) {
									state[i] = settings.finalState[i];
									board.state[i] = state[i];
								}
								transitionBarWidth = 0;
								xPage = 0;
								prevPage = 1;
								nextPage = 2;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 2) {
								xPage = 0;
								xSettings = getWidth();
								prevPage = 1;
								nextPage = 3;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 3) {
								xPage = 0;
								xInstruction = getWidth();
								prevPage = 1;
								nextPage = 4;
								transitionPhase = 1;
								pageId = 6;
								drawInstruction(instruction, xInstruction, yInstruction);
							} else if (index == 4) {
								xPage = 0;
								xAbout = (getWidth()*3)/2;
								prevPage = 1;
								nextPage = 5;
								transitionPhase = 1;
								pageId = 6;
							} else if (index == 5) {
								if (ad.showed == true) {
									midlet.exitMIDlet();
								} else {
									ad.showed = true;
								}
							}
						break;
					}
					if (keyCode == -7) {
						midlet.exitMIDlet();
					}
				break;
				//------------------------------------------------------------------
				case 2: // Simulation Page
					if (!solving) {
						switch (gameCode) {
							case UP:
								if (!solving)
									moveDown(state);
							break;
							case DOWN:
								if (!solving)
									moveUp(state);
							break;
							case LEFT:
								if (!solving)
									moveRight(state);
							break;
							case RIGHT:
								if (!solving)
									moveLeft(state);
							break;
							case FIRE:
								
							break;                            
						}
						if (keyCode == -7) {
							xPage = -getWidth();
							prevPage = 2;
							nextPage = 1;
							transitionPhase = 1;
							pageId = 6;
						} else if (keyCode == -6) {
							randomize(settings.step, state);
						}
						resultState = false;
					} else {
						// do nothing
					}
				break;
				//------------------------------------------------------------------
				case 3: // Settings
					switch (gameCode) {
						case UP:
							if (settings.index > 0)
								settings.index--;
							else
								settings.index = 3;
						break;
						case DOWN:
							if (settings.index < 3)
								settings.index++;
							else
								settings.index = 0;
						break;
						case LEFT:
							switch (settings.index) {
								case 0:
									if (settings.solverChooser > 1)
										settings.solverChooser--;
									else
										settings.solverChooser = 6;
								break;
								case 1:
									if (settings.stateChooser > 1)
										settings.stateChooser--;
									else
										settings.stateChooser = 3;
								break;
								case 2:
									if (settings.step > 1)
										settings.step--;
								break;
								case 3:
									if (settings.delay > 10)
										settings.delay = settings.delay - 10;
								break;
							}
						break;
						case RIGHT:
							switch (settings.index) {
								case 0:
									if (settings.solverChooser < 6)
										settings.solverChooser++;
									else
										settings.solverChooser = 1;
								break;
								case 1:
									if (settings.stateChooser < 3)
										settings.stateChooser++;
									else
										settings.stateChooser = 1;
								break;
								case 2:
									if (settings.step < 50)
										settings.step++;
								break;
								case 3:
									if (settings.delay < 500)
										settings.delay = settings.delay + 10;
								break;
							}
						break;
						case FIRE:
							
						break;
					}
					if (keyCode == -7) {
						xPage = -getWidth();
						xSettings = 0;
						prevPage = 3;
						nextPage = 1;
						transitionPhase = 1;
						pageId = 6;
					}
				break;
				//------------------------------------------------------------------
				case 4: // Instruction
					switch (gameCode) {
						case UP:
							if (instructionHeight > windowHeight) {
								if (yInstruction < 30) {
									yInstruction += 20;
								} else {
									yInstruction = 50;
								}
								drawInstruction(instruction, xInstruction, yInstruction);
							}
						break;
						case DOWN:
							if (instructionHeight > windowHeight) {
								if (yInstruction > 70 - (instructionHeight - windowHeight)) {
									yInstruction -= 20;
								} else {
									yInstruction = 50 - instructionHeight + windowHeight;
								}
								drawInstruction(instruction, xInstruction, yInstruction);
							}
						break;
						case FIRE:
							xPage = -getWidth();
							xInstruction = 0;
							prevPage = 4;
							nextPage = 1;
							transitionPhase = 1;
							pageId = 6;
						break;
					}
				break;
				//------------------------------------------------------------------
				case 5: // About
					switch (gameCode) {
						case FIRE:
							xPage = -getWidth();
							xAbout = getWidth()/2;
							prevPage = 5;
							nextPage = 1;
							transitionPhase = 1;
							pageId = 6;
						break;
					}
				break;
			}
		}
        repaint();
    }

    public void run() {
		if (ad.showed == true) {
			ad.run();
			if (ad.type == AlertDialog.ALERTDIALOG_PROGRESS) {
				repaint();
			}
		} else {
			switch (pageId) {
				case 2:

				break;
				case 6:
					switch (prevPage) {
						case 1:
							if (nextPage == 2) {
								if (transitionPhase == 1) {
									if (xPage > -getWidth()) {
										xPage = xPage - 20;
									} else {
										xPage = -getWidth();
										transitionPhase = 2;
									}
									repaint();
								} else if (transitionPhase == 2) {
									if (transitionBarWidth < 196) {
										transitionBarWidth = transitionBarWidth + 1;
									} else {
										transitionBarWidth = 196;
										transitionPhase = 3;
									}
									repaint();
								} else if (transitionPhase == 3) {
									if (xBoard > getWidth()/2) {
										xBoard = xBoard - 20;
									} else {
										xBoard = getWidth()/2;
										transitionPhase = 0;
										pageId = 2;
									}
									repaint();
								}
							} else if (nextPage == 3) {
								if (transitionPhase == 1) {
									if (xPage > -getWidth()) {
										xPage = xPage - 20;
									} else {
										xPage = -getWidth();
										//transitionPhase = 0;
									}
									if (xSettings > 0) {
										xSettings = xSettings - 20;
									} else {
										xSettings = 0;
										transitionPhase = 0;
										pageId = 3;
									}
									repaint();
								}
							} else if (nextPage == 4) {
								if (transitionPhase == 1) {
									if (xPage > -getWidth()) {
										xPage = xPage - 20;
									} else {
										xPage = -getWidth();
										//transitionPhase = 0;
									}
									if (xInstruction > 0) {
										xInstruction = xInstruction - 20;
									} else {
										xInstruction = 0;
										transitionPhase = 0;
										pageId = 4;
									}
									repaint();
								}
							} else if (nextPage == 5) {
								if (transitionPhase == 1) {
									if (xPage > -getWidth()) {
										xPage = xPage - 20;
									} else {
										xPage = -getWidth();
										//transitionPhase = 0;
									}
									if (xAbout > getWidth()/2) {
										xAbout = xAbout - 20;
									} else {
										xAbout = getWidth()/2;
										transitionPhase = 0;
										pageId = 5;
									}
									repaint();
								}
							}
						break;
						case 2:
							if (nextPage == 1) {
								if (transitionPhase == 1) {
									if (xPage < 0) {
										xPage = xPage + 20;
									} else {
										xPage = getWidth();
										//transitionPhase = 0;
									}
									if (xBoard < (getWidth()*3)/2) {
										xBoard = xBoard + 20;
									} else {
										xBoard = getWidth()/2;
										transitionPhase = 0;
										pageId = 1;
									}
									repaint();
								}
							}
						break;
						case 3:
							if (nextPage == 1) {
								if (transitionPhase == 1) {
									if (xPage < 0) {
										xPage = xPage + 20;
									} else {
										xPage = getWidth();
										//transitionPhase = 0;
									}
									if (xSettings < getWidth()) {
										xSettings = xSettings + 20;
									} else {
										xSettings = getWidth();
										transitionPhase = 0;
										pageId = 1;
									}
									repaint();
								}
							}
						break;
						case 4:
							if (nextPage == 1) {
								if (transitionPhase == 1) {
									if (xPage < 0) {
										xPage = xPage + 20;
									} else {
										xPage = getWidth();
										//transitionPhase = 0;
									}
									if (xInstruction < getWidth()) {
										xInstruction = xInstruction + 20;
									} else {
										xInstruction = getWidth();
										transitionPhase = 0;
										pageId = 1;
									}
									repaint();
								}
							}
						break;
						case 5:
							if (nextPage == 1) {
								if (transitionPhase == 1) {
									if (xPage < 0) {
										xPage = xPage + 20;
									} else {
										xPage = getWidth();
										//transitionPhase = 0;
									}
									if (xAbout < (getWidth()*3)/2) {
										xAbout = xAbout + 20;
									} else {
										xAbout = (getWidth()*3)/2;
										transitionPhase = 0;
										pageId = 1;
									}
									repaint();
								}
							}
						break;
					}
				break;
			}
		}

        //throw new UnsupportedOperationException("Not supported yet.");
    }

    public String strArray(int[] array) {
        String temp = "[ ";
        for (int i=0; i < array.length; i++) {
            temp = temp + Integer.toString(array[i]) + " ";
        }
        temp = temp + "]";
        return temp;
    }

	/*
	 * Split one lateral String parameter into array of words, blank characters are ignored.
	 *	@param:
	 *		String		str
	 *	@return:
	 *		String[]	result
	 *
	 *	@Andik, 2010-08-26
	 */
	private String[] splitString(String str) {
		int strLength = str.length();
		int nbWords = 0;
		boolean startCounting = false;
		for (int i = 0; i < strLength; i++) {
			if (str.charAt(i) == ' ') {
				if (startCounting == true) {
					nbWords++;
					startCounting = false;
				}
			} else {
				startCounting = true;
			}
			if (i == strLength - 1) {
				if (str.charAt(strLength-1) != ' ') {
					nbWords++;
					startCounting = false;
				}
			}
		}
		// for debugging purpose only ------
		//System.out.println("Jumlah Kata = " + nbWords);
		// ------------
		String[] result = new String[nbWords];
		for (int i = 0; i < nbWords; i++) {
			result[i] = "";
		}
		int resultIndex = 0;
		startCounting = false;
		for (int i = 0; i < strLength; i++) {
			if (str.charAt(i) == ' ') {
				if (startCounting == true) {
					startCounting = false;
					resultIndex++;
				}
			} else {
				startCounting = true;
				result[resultIndex] += str.charAt(i);
			}
		}
		// for debugging purpose only ------
		//for (int i = 0; i < nbWords; i++) {
		//	System.out.println(result[i]);
		//}
		// ------------
		return result;
	}
	
	/*
	 * Draw wrap text into graphics context from array of words with certain properties 
		and area parameters. Assumption: the value of area's width is reasonable enough 
		compared to the width of each words.
	 *	@param:
	 *		Graphics g
	 *		String[] words
	 *		Font f
	 *		int color
	 *		int space
	 *		int xArea
	 *		int yArea
	 *		int widthArea
	 *
	 *	@Andik, 2010-08-26
	 */
	public void drawWrapText(Graphics g, String[] words, Font f, int color, int space, 
		int xArea, int yArea, int widthArea) {
		int fontHeight = f.getHeight();
		int interval = fontHeight * space;
		int currentPos = xArea;
		int currentWidth = f.stringWidth(words[0]);
		int tempWidth = 0;
		g.setFont(f);
		g.setColor(color);
		for (int i = 0; i < words.length; i++) {
			if (tempWidth + f.stringWidth(words[i]) >= widthArea) {
				yArea += interval;
				currentPos = xArea;
			}
			g.drawString(words[i], currentPos, yArea, Graphics.LEFT | Graphics.TOP);
			currentWidth = f.stringWidth(words[i]) + 3;
			currentPos += currentWidth;
			tempWidth = currentPos - xArea;
			// for debugging purpose only ------
			//System.out.println(currentWidth);
			//System.out.println(words[i]);
			// ------------
		}
	}

	/*
	 * Calculate wrap text area.
	 *	@param:
	 *		Graphics g
	 *		String[] words
	 *		Font f
	 *		int color
	 *		int space
	 *		int xArea
	 *		int yArea
	 *		int widthArea
	 *
	 *	@Andik, 2010-08-27
	 */
	public int calculateArea(Graphics g, String[] words, Font f, int color, int space, 
		int xArea, int yArea, int widthArea) {
		int firstLine = yArea;
		int fontHeight = f.getHeight();
		int interval = fontHeight * space;
		int currentPos = xArea;
		int currentWidth = f.stringWidth(words[0]);
		int tempWidth = 0;
		g.setFont(f);
		g.setColor(color);
		for (int i = 0; i < words.length; i++) {
			if (tempWidth + f.stringWidth(words[i]) >= widthArea) {
				yArea += interval;
				currentPos = xArea;
			}
			currentWidth = f.stringWidth(words[i]) + 3;
			currentPos += currentWidth;
			tempWidth = currentPos - xArea;
		}
		return (yArea - firstLine + fontHeight);
		// for debugging purpose only ------
		//System.out.println("Tingginya = " + this.height);
		// ------------
	}
}
